﻿Imports System.Runtime.CompilerServices

Namespace Load

    ''' <summary>
    ''' ICollection拡張メソッド
    ''' </summary>
    ''' <remarks></remarks>
    Public Module ICollectionExtension

        ''' <summary>
        ''' LazyListに型変換を行います
        ''' </summary>
        ''' <typeparam name="T"></typeparam>
        ''' <param name="source"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        <Extension()>
        Public Function ToLazy(Of T)(source As ICollection(Of T)) As LazyList(Of T)
#If DEBUG Then
            If TypeOf source Is LazyList(Of T) = False Then Throw New InvalidOperationException
#End If
            Return DirectCast(source, LazyList(Of T))
        End Function

        ''' <summary>
        ''' 現在のコレクションを廃棄し、LazyListに型変換を行います
        ''' </summary>
        ''' <typeparam name="MyT">親の型</typeparam>
        ''' <typeparam name="ChildT">子の型</typeparam>
        ''' <param name="source">子インスタンス</param>
        ''' <param name="r">ローダー</param>
        ''' <param name="owner">親インスタンス</param>
        ''' <returns></returns>
        ''' <remarks>
        ''' コネクション切断後に再度Fetchさせたい場合はこちらのメソッドを使用してください。
        ''' 現在の子インスタンスは破棄されることに注意してください。
        ''' #112 ConnectionをCloseした後でもフェッチできるようにする
        ''' </remarks>
        <Extension()>
        Public Function ToInitLazy(Of MyT, ChildT)(source As ICollection(Of ChildT), r As ModelLoader, owner As MyT) As LazyList(Of ChildT)
            Dim ownerList As New QueryableList(Of MyT)(r, owner)
            Dim prop = (From el In owner.GetType.GetProperties Where el.CanRead AndAlso el.CanWrite AndAlso el.GetIndexParameters.Any = False AndAlso source.Equals(el.GetValue(owner, Nothing))).FirstOrDefault
#If DEBUG Then
            If prop Is Nothing Then Throw New InvalidOperationException
#End If

            'LazyListをインスタンス、代入
            Dim rels = owner.GetType.ToTable.ChildRelations.Where(Function(x) x.CollectionProperty.Equals(prop))
            Dim q = r.From(Of ChildT).Provider.CreateChildQuery(Of MyT, ChildT)(ownerList, rels)
            CollectionInitializer.InitAsLasy(owner, rels, q)

            '差し替えたリストを取得する
            Return DirectCast(prop.GetValue(owner, Nothing), LazyList(Of ChildT))
        End Function

        ''' <summary>
        ''' 現在のコレクションを廃棄し、LazyListに型変換を行います
        ''' </summary>
        ''' <typeparam name="ChildT">子の型</typeparam>
        ''' <param name="source">子インスタンス</param>
        ''' <param name="cn">DBコネクション</param>
        ''' <returns></returns>
        ''' <remarks>
        ''' コネクション切断後に再度Fetchさせたい場合はこちらのメソッドを使用してください。
        ''' 現在の子インスタンスは破棄されることに注意してください。
        ''' #112 ConnectionをCloseした後でもフェッチできるようにする
        ''' </remarks>
        <Extension()>
        Public Function ToLazy(Of ChildT)(source As ICollection(Of ChildT), cn As IDbConnection) As LazyList(Of ChildT)
            Dim lst = source.ToLazy
            lst.Loader.SetConnection(cn)
            Return lst
        End Function
    End Module

End Namespace
